/**
 *	@file	radio_kouza.c
 *	@brief	ラジオ　ポケモン講座データ生成
 *	@author	Miyuki Iwasawa
 *	@date	09.04.17
 */

#include "common.h"
#include "system/procsys.h"
#include "system/arc_util.h"
#include "system/arc_tool.h"
#include "system/bmp_list.h"
#include "system/bmp_menu.h"
#include "system/pm_str.h"
#include "system/msgdata.h"
#include "system/fontproc.h"
#include "system/snd_tool.h"
#include "system/buflen.h"
#include "system/wordset.h"
#include "system/pm_rtc.h"
#include "application/app_tool.h"
#include "msgdata/msg.naix"

#include "field/zonedata.h"
#include "field/encount_dat.h"
#include "field/generate_zone.h"
#include "field/evwkdef.h"
#include "field/sysflag.h"
#include "field/sysflag_def.h"
#include "fielddata/script/saveflag.h"
#include "fielddata/maptable/zone_id.h"
#include "savedata/zukanwork.h"
#include "savedata/encount.h"
#include "radio_prog.h"
#include "msgdata/msg_pg_radio.h"
#include "msgdata/msg_radio_p_kouza.h"

//------------------------------------------------------------------
/**
 * @brief	ゾーン毎のエンカウントデータの読み込み
 * @param	zone_id		ゾーンIDの指定
 * @param	event_data	EVENT_DATA構造体へのポインタ
 *
 * ホントはfield/eventdata.hをインクルードするべきだけど、
 * そうするとFIELDSYS_WORK他が参照できないといけなくなるので特別に直接extern
 */
//------------------------------------------------------------------
extern void EventData_LoadEncountData(GS_ENCOUNT_DATA *enc_data, int zone_id);

#define KOUZA_DATA_MAX	(16)
#define TOPIC_CT_MAX	(5)
#define ENCOUNT_ZONE_MAX	(150)	//注：コンバータから出力されないので手入力
#define ENC_POKE_MAX	((ENC_MONS_NUM_NORMAL*3)+ENC_MONS_NUM_SEA+ENC_MONS_NUM_ROCK+(ENC_MONS_NUM_FISH*3)+1)
#define KURUMI_WORD_MAX	(13)

//除外ゾーンテーブル
static const u16 DATA_EgnoreZone[] = {
 ZONE_ID_D02R0103,	//お月見山外
 ZONE_ID_D02R0104,	//お月見山外イベント時
 ZONE_ID_D22R0102,	//自然公園（虫取り大会開催中）
 ZONE_ID_D24R0205,	//アルフの遺跡：像の間
 ZONE_ID_D24R0216,	//アルフの遺跡：像の間、小部屋変化後
 ZONE_ID_D24R0217,	//アルフの遺跡：像の間の上の小部屋、エンカウントする
 ZONE_ID_D24R0218,	//アルフの遺跡：像の間、小部屋変化後、エンカウントする小部屋につながる
 ZONE_ID_D39R0102,	//氷の抜け道Ｂ１Ｆ
 ZONE_ID_D39R0103,	//氷の抜け道Ｂ２Ｆ
 ZONE_ID_D39R0104,	//氷の抜け道Ｂ３Ｆ　※エンカウントするポケモンがまったく同じなので除外
 ZONE_ID_D40R0102,	//うずまきじまB1F
 ZONE_ID_D40R0104,	//うずまきじまB2F　※エンカウントするポケモンがまったく同じなので除外
 ZONE_ID_D45R0102,	//トージョウの滝奥
 ZONE_ID_D47R0102,	//サファリゾーン内
};

#define EGNORE_ZONE_MAX	(NELEMS(DATA_EgnoreZone))

typedef struct{
 int heapID;
 u16 seq;
 u16 gene_poke;
 u16 gene_zone;

 u16 enczone_num;
 u16 encpoke_anum;
 u16 encpoke_bnum;
 u16 data[TOPIC_CT_MAX][2];
 u16 kurumi[TOPIC_CT_MAX][2];

 u16 enc_zone[ENCOUNT_ZONE_MAX];
 u16 enc_poke_a[ENC_POKE_MAX];
 u16 enc_poke_b[ENC_POKE_MAX];
 u8	topic_ct;
}RADIO_KOUZA_WORK;

static void kouza_ResInit(PM_RADIO_MAN* man);
static void kouza_ResRelease(PM_RADIO_MAN* man);
static void kouza_SearchZoneTable(PM_RADIO_MAN* man,RADIO_KOUZA_WORK* wk);
static BOOL kouza_TopicConflictCheck(RADIO_KOUZA_WORK* wk,u16 value, u8 max);
static u16 kouza_GetEncountPoke(RADIO_KOUZA_WORK* wk,ZUKAN_WORK* zukan,u16 zone_id);

#include "system/snd_radio.h"

/**
 *	@brief	ラジオ　ポケモン講座　初期化
 */
int RadioKouza_Init(PM_RADIO_MAN* man)
{
	RADIO_KOUZA_WORK* wk = NULL;

	wk = sys_AllocMemory(man->heapID,sizeof(RADIO_KOUZA_WORK));
	MI_CpuClear8(wk,sizeof(RADIO_KOUZA_WORK));

	man->ch_wk = (void*)wk;

	kouza_ResInit(man);

	//再生開始
	Snd_BgmStop(Snd_NowBgmNoGet(),0);
	RADIO_PLAY(RADIO_BGM_KOUZA);
//	PMGS_PlayRadio(RADIO_BGM_KOUZA);
	return 0;
}

/**
 *	@brief	ラジオ　ポケモン講座 解放
 */
int RadioKouza_End(PM_RADIO_MAN* man)
{
	kouza_ResRelease(man);

	MI_CpuClear8(man->ch_wk,sizeof(RADIO_KOUZA_WORK));
	sys_FreeMemoryEz(man->ch_wk);
	man->ch_wk = NULL;

	return 0;
}

/**
 *	@brief	ラジオ　ポケモン講座 再生メイン
 */
int RadioKouza_Play(PM_RADIO_MAN* man)
{
	int i;
	RADIO_KOUZA_WORK* wk = (RADIO_KOUZA_WORK*)man->ch_wk;

	switch(wk->seq){
	case 0:	//ポケモン講座タイトルコール再生
		RadioSub_SentencePlay(man,m_kouza_00_01);
		wk->seq++;
		break;
	case 1:
		if(!RadioSub_SentencePlayWait(man)){
			break;
		}
		//大量発生トピックスがあるか？
		if(wk->gene_poke == 0){
			wk->seq = 3;
			break;
		}
		//大量発生トピックス再生
		WORDSET_RegisterPlaceName( man->wset,0, ZoneData_GetPlaceNameID(wk->gene_zone));
		WORDSET_RegisterMonsName( man->wset, 1, wk->gene_poke);
		RadioSub_SentencePlay(man,m_news_01);
		wk->seq++;
		break;
	case 2:
		if(!RadioSub_SentencePlayWait(man)){
			break;
		}
		wk->seq++;
		//ここはスルー
	case 3:	//トピック再生
		//ワードセット
		WORDSET_RegisterPlaceName( man->wset,0, wk->data[wk->topic_ct][0]);
		WORDSET_RegisterMonsName( man->wset, 1, wk->data[wk->topic_ct][1]);
		IWASAWA_PRINT("ポケモン講座 %d -> map = %d, mons = %d\n",
				wk->topic_ct,wk->data[wk->topic_ct][0],wk->data[wk->topic_ct][1]);
		RadioSub_SentencePlay(man,m_kouza_01_01);
		wk->seq++;
		break;
	case 4:
		if(!RadioSub_SentencePlayWait(man)){
			break;
		}
		for(i = 0;i < 2;i++){
			MSGMAN_GetString(man->msg_prog,
				wk->kurumi[wk->topic_ct][i]+m_kouza_03_01+(KURUMI_WORD_MAX*i),man->str_tmp);
			WORDSET_RegisterWord( man->wset, 2+i, man->str_tmp, PM_FEMALE, TRUE, PM_LANG);
		}
		RadioSub_SentencePlay(man,m_kouza_02_01);
		wk->seq++;
		break;
	case 5:
		if(!RadioSub_SentencePlayWait(man)){
			break;
		}
		if(++wk->topic_ct < TOPIC_CT_MAX){
			wk->seq = 3;
			break;
		}
		wk->seq++;
		break;
	case 6:
		if(!RadioSub_MsgWaitScroll(man)){
			break;
		}
		//アイキャッチ
		RadioSub_EyeCatchPlay(man,m_kouza_00_02);
		wk->seq++;
		break;
	case 7:
		if(!RadioSub_EyeCatchPlayWait(man)){
			break;
		}
		//CMリクエスト
		man->cm_req_f = TRUE;
		return 1;
	}
	return 0;
}

/*
 *	@brief	ポケモン講座用 必要なデータを初期化する
 */
static void kouza_ResInit(PM_RADIO_MAN* man)
{
	int i,ofs;
	u8 idx1,idx2;
	RADIO_KOUZA_WORK* wk = (RADIO_KOUZA_WORK*)man->ch_wk;
	ENC_SV_PTR enc_sv;

	man->msg_prog = MSGMAN_Create(MSGMAN_TYPE_NORMAL,ARC_MSG,NARC_msg_radio_p_kouza_dat,man->heapID);

	//番組タイトルとDJ名を通知
	MSGMAN_GetString(man->msg_prog,m_kouza_title,man->str_title);
	MSGMAN_GetString(man->msg_prog,m_kouza_dj,man->str_dj);

	//大量発生チェック
	enc_sv = EncDataSave_GetSaveDataPtr(man->save);

	if ( EncDataSave_IsGenerate(enc_sv) ){
		//ランダムの種を元に大量発生する場所を割り出す
		GenerateZone_GetInfo(EncDataSave_GetRandSeed(enc_sv, ENC_RND_SEED_GENERATE),
			&wk->gene_zone, &wk->gene_poke);
	}
	//トピック抽選
	kouza_SearchZoneTable(man,wk);

	//クルミのワード抽選
	ofs = (gf_rand()%3+1)*2;
	idx1 = gf_rand()%KURUMI_WORD_MAX;
	idx2 = gf_rand()%KURUMI_WORD_MAX;
	for(i = 0;i < TOPIC_CT_MAX;i++){
		wk->kurumi[i][0] = idx1;
		wk->kurumi[i][1] = idx2;

		idx1 = (idx1+ofs)%KURUMI_WORD_MAX;
		idx2 = (idx2+ofs)%KURUMI_WORD_MAX;
	}
}

/**
 *	@brief	ポケモン講座用　リソース解放
 */
static void kouza_ResRelease(PM_RADIO_MAN* man)
{
	RADIO_KOUZA_WORK* wk = (RADIO_KOUZA_WORK*)man->ch_wk;

	MSGMAN_Delete(man->msg_prog);
}

/**
 *	@brief	抽選候補ゾーンテーブル
 */
static void kouza_SearchZoneTable(PM_RADIO_MAN* man,RADIO_KOUZA_WORK* wk)
{
	int i,j;
	BOOL arrive_r47;
	ZUKAN_WORK* zukan = SaveData_GetZukanWork(man->save);

	arrive_r47 = SysFlag_Arrive( SaveData_GetEventWork(man->save), SYSFLAG_MODE_CHECK, FLAG_ARRIVE_R47);
	MI_CpuClear8(wk->enc_zone,sizeof(u16)*ENCOUNT_ZONE_MAX);
	MI_CpuClear8(wk->enc_poke_a,sizeof(u16)*ENC_POKE_MAX);
	MI_CpuClear8(wk->enc_poke_b,sizeof(u16)*ENC_POKE_MAX);

	wk->enczone_num = 0;
	wk->encpoke_anum = 0;
	wk->encpoke_bnum = 0;
	for(i  = 0;i < ZONE_ID_MAX;i++){
		//エンカウントチェック
		if(!ZoneData_GetEncountFlag(i)) {
			continue;
		}
		//エリアチェック
		if(ZoneData_IsKanto(i) != man->is_kanto_f){
			continue;
		}
		//除外ゾーンチェック
		for(j = 0;j < EGNORE_ZONE_MAX;j++){
			if(i == DATA_EgnoreZone[j]){
				break;
			}
		}
		if(j < EGNORE_ZONE_MAX){
			continue;	//除外ゾーン
		}
		if(!arrive_r47){
			if(i == ZONE_ID_R47 || i == ZONE_ID_R48){
				continue;
			}
		}
		wk->enc_zone[wk->enczone_num++] = i;
		if(wk->enczone_num >= ENCOUNT_ZONE_MAX){
			GF_ASSERT(0);
			break;
		}
	}
	//5つのゾーンを抽選
	for(i = 0;i < TOPIC_CT_MAX;i++)	{
		u16 value,place;

		wk->encpoke_anum = 0;
		wk->encpoke_bnum = 0;

		do{
			value = (gf_rand()%wk->enczone_num);
			place = ZoneData_GetPlaceNameID(wk->enc_zone[value]);
		}while(kouza_TopicConflictCheck(wk,place,i));
		wk->data[i][0] = place;

		//そのゾーンでエンカウントするポケモンを抽選
		wk->data[i][1] = kouza_GetEncountPoke(wk,zukan,wk->enc_zone[value]);
	}
}

/**
 *	@brief	かぶらないようにトピック抽選
 */
static BOOL kouza_TopicConflictCheck(RADIO_KOUZA_WORK* wk,u16 value, u8 max)
{
	int i;

	for(i = 0;i < max;i++){
		if(value == wk->data[i][0]){
			return TRUE;
		}
	}
	return FALSE;
}

/**
 *	@brief	ポケモンの重複チェック
 */
static void kouza_AddPokeList(RADIO_KOUZA_WORK* wk,ZUKAN_WORK* zukan,u16 monsno)
{
	int i;

	if(monsno == 0 || monsno > MONSNO_END ){
		return;
	}
	for(i = 0;i < wk->encpoke_anum;i++){
		if(wk->enc_poke_a[i] == monsno){
			return;
		}
	}
	wk->enc_poke_a[wk->encpoke_anum++] = monsno;
	//図鑑に未登録ポケモンのみリスト
	if(!ZukanWork_GetPokeGetFlag(zukan, monsno)){
		wk->enc_poke_b[wk->encpoke_bnum++] = monsno;
	}
}

/**
 *	@brief	そのゾーンでエンカウントするポケモンを抽選
 */
static u16 kouza_GetEncountPoke(RADIO_KOUZA_WORK* wk,ZUKAN_WORK* zukan,u16 zone_id)
{
	int i;
	GS_ENCOUNT_DATA enc;

	IWASAWA_PRINT("ポケモン講座　エンカウントゲット map = %d end_idx = %d\n",zone_id,ZoneData_GetEncountArchiveID(zone_id));
	EventData_LoadEncountData(&enc, zone_id);

	if(enc.EncProbGround != 0){	//地面エンカウント
		for(i = 0;i < ENC_MONS_NUM_NORMAL;i++){
			kouza_AddPokeList(wk,zukan,enc.GrndPokeM[i]);
			kouza_AddPokeList(wk,zukan,enc.GrndPokeD[i]);
			kouza_AddPokeList(wk,zukan,enc.GrndPokeN[i]);
		}
	}
	if(enc.EncProbSea != 0){	//水上エンカウント
		for(i = 0;i < ENC_MONS_NUM_SEA;i++){
			kouza_AddPokeList(wk,zukan,enc.EncSea[i].MonsterNo);
		}
	}
	if(enc.EncProbRock != 0){	//いわくだきエンカウント
		for(i = 0;i < ENC_MONS_NUM_ROCK;i++){
			kouza_AddPokeList(wk,zukan,enc.EncRock[i].MonsterNo);
		}
	}
	if(enc.EncProbFish1 != 0){	//ボロの釣り竿エンカウント
		for(i = 0;i < ENC_MONS_NUM_FISH;i++){
			kouza_AddPokeList(wk,zukan,enc.EncFish1[i].MonsterNo);
		}
	}
	if(enc.EncProbFish2 != 0){	//いい釣り竿エンカウント
		for(i = 0;i < ENC_MONS_NUM_FISH;i++){
			kouza_AddPokeList(wk,zukan,enc.EncFish2[i].MonsterNo);
		}
	}
	if(enc.EncProbFish3 != 0){	//すごい釣り竿エンカウント
		for(i = 0;i < ENC_MONS_NUM_FISH;i++){
			kouza_AddPokeList(wk,zukan,enc.EncFish3[i].MonsterNo);
		}
	}
	if(enc.FishingNightPoke != 0){	//夜釣り
		kouza_AddPokeList(wk,zukan,enc.FishingNightPoke);
	}
	//候補から抽選
	if(	(wk->encpoke_bnum == 0) ||
		((wk->encpoke_bnum == 1) && ((gf_rand()%1000) < 500))){
		return wk->enc_poke_a[gf_rand()%wk->encpoke_anum];
	}else{
		return wk->enc_poke_b[gf_rand()%wk->encpoke_bnum];
	}
}
